package locker

import (
	"sync"
	"sync/atomic"
	"time"
)

type STATUS = uint32

const (
	LOCKED   STATUS = 1
	UNLOCKED STATUS = 0
)

type Locker interface {
	Lock(key string, block bool) bool
	Unlock(key string) bool
	Free()
}
type locker struct {
	timestamp int64
	lock      uint32
}
type myLocker struct {
	lockers map[string]*locker
	lock    sync.Mutex
}

func (this *myLocker) Lock(key string, block bool) bool {
	l, ok := this.lockers[key]
	if !ok {
		this.lock.Lock()
		l, ok = this.lockers[key]
		if !ok {
			timestap := time.Now().Unix()
			this.lockers[key] = &locker{
				timestap,
				LOCKED,
			}
			this.lock.Unlock()
			return true
		}
		this.lock.Lock()
	}

	if block {
		for {
			if atomic.CompareAndSwapUint32(&l.lock, UNLOCKED, LOCKED) {
				return true
			}
		}

	}
	return atomic.CompareAndSwapUint32(&l.lock, UNLOCKED, LOCKED)
}
func (this *myLocker)Unlock(key string) bool {
	l,ok := this.lockers[key]
	if !ok{
		return false
	}
	return atomic.CompareAndSwapUint32(&l.lock,LOCKED,UNLOCKED)
}
func (this *myLocker)Free()  {
	for key,locker:= range this.lockers{
		if (locker.timestamp + 10) < time.Now().Unix(){
			delete(this.lockers,key)
		}
	}
}
func NewLocker()Locker  {
	l := &myLocker{}
	l.lockers = make(map[string]*locker)
	return l
}